#include "MemoryProfiler.h"
#include "Utils.h"
#include <syslog.h>
#include <stdlib.h>

map<Function*, vector<MemoryProfiler*> > MemoryProfiler::ofFunc;
vector<MemoryProfiler*> MemoryProfiler::all;
bool MemoryProfiler::Enabled = true;

void MemoryProfilerAlarmHandler(int)
{
	for (vector<MemoryProfiler*>::iterator i = MemoryProfiler::all.begin(), e = MemoryProfiler::all.end(); i != e; ++i)
		(*i)->Total = 0;
//	puts("cleared counters");

	if (MemoryProfiler::Enabled)
		alarm(1);
}

MemoryProfiler::MemoryProfiler(LoadInst *Inst, void*) : Inst(Inst), Misses(0), Total(0)
{
	ofFunc[Inst->getParent()->getParent()].push_back(this);
}

bool MemoryProfiler::Profile(void *Addr)
{
	if (Total >= 100) {
		return false;
	}
	++Total;
//	if (Total == 50)
//	{
//		errs() << "ignoring " << *Inst << " from now on\n";
//	}
//	errs() << "iscached (" <<Total << ") for " << *Inst << "\n";

	if (isCached(Addr))
		return false;
	errs() << "found miss\n";
	++Misses;

	return true;
}
vector<TerminatingMemoryProfiler*> TerminatingMemoryProfiler::profilers;

TerminatingMemoryProfiler::TerminatingMemoryProfiler(LoadInst *Inst, void*) : Inst(Inst), Misses(0)
{
	num = profilers.size();
	profilers.push_back(this);
}

void TerminatingMemoryProfiler::Profile(void *Addr)
{
//	errs() << "In TerminatingMemoryProfiler::Profile\n";
	if (!isCached(Addr) && ++Misses > 2) {
		errs() << "Terminating due to cache miss on " << *Inst << "\n";
		exit(num + 1);
	}
}
